<template>
  <el-scrollbar class="side-scroll-bar">
    <div class="panel-container">

      <el-tabs v-model="firstTab" class="no-bottom-margin indent-left-margin">

        <el-tab-pane v-if="showChartLib" name="chartLib">
          <template #label>
            <span><svg-icon icon-class="el-chart" /> {{ i18nt('designer.chartLib') }}</span>
          </template>

          <el-collapse v-model="activeNames" class="widget-collapse">
            <el-collapse-item name="1" :title="i18nt('designer.containerTitle')">
              <!-- 图表组件不支持拖拽添加到画布，必须鼠标双击添加！！ -->
              <draggable tag="ul" :list="chartContainers" item-key="key"
                :group="{ name: 'dragGroup', pull: 'clone', put: false }" :clone="handleContainerWidgetClone"
                ghost-class="ghost" :sort="false" :disabled="true" :move="checkContainerMove" @end="onContainerDragEnd">
                <template #item="{ element: ctn }">
                  <li class="chart-container-widget-item" :title="ctn.displayName"
                    @dblclick="addChartContainerByDbClick(ctn)">
                    <div class="svg-icon-label">
                      <svg-icon :icon-class="ctn.icon" class-name="color-svg-icon" />
                      <span class="chart-widget-item__label">{{getWidgetLabel(ctn)}}</span>
                    </div>
                  </li>
                </template>
              </draggable>
            </el-collapse-item>

            <el-collapse-item name="2" :title="i18nt('designer.chartTitle')">
              <!-- 图表组件不支持拖拽添加到画布，必须鼠标双击添加！！ -->
              <draggable tag="ul" :list="chartWidgets" item-key="key"
                :group="{ name: 'dragGroup', pull: 'clone', put: false }" :move="checkFieldMove" :disabled="true"
                :clone="handleFieldWidgetClone" ghost-class="ghost" :sort="false">
                <template #item="{ element: chart }">
                  <li class="chart-widget-item" :title="chart.displayName" @dblclick="addChartByDbClick(chart)">
                    <div class="svg-icon-label">
                      <svg-icon :icon-class="chart.icon" class-name="color-svg-icon" />
                      <span class="chart-widget-item__label">{{ getWidgetLabel(chart) }}</span>
                    </div>
                  </li>
                </template>
              </draggable>
            </el-collapse-item>
          </el-collapse>

        </el-tab-pane>

        <el-tab-pane v-if="showMetadataLib" name="metadataLib">
          <template #label>
            <span><svg-icon icon-class="el-module" /> {{ i18nt('designer.metadataLib') }}</span>
          </template>

          <el-collapse v-model="metadataActiveNames" class="widget-collapse">
            <el-collapse-item name="0" :title="i18nt('designer.containerTitle')">
              <draggable tag="ul" :list="commonContainers" item-key="key"
                :group="{ name: 'dragGroup', pull: 'clone', put: false }" :clone="handleContainerWidgetClone"
                ghost-class="ghost" :sort="false" :move="checkContainerMove" @end="onContainerDragEnd">
                <template #item="{ element: ctn }">
                  <li class="container-widget-item" :title="ctn.displayName" @dblclick="addContainerByDbClick(ctn)">
                    <span><svg-icon :icon-class="ctn.icon" class-name="color-svg-icon" />{{ getWidgetLabel(ctn)
                      }}</span>
                  </li>
                </template>
              </draggable>
            </el-collapse-item>

            <template v-if="metaFields.main.entityName">
              <el-collapse-item name="1" :title="metaFields.main.entityLabel">
                <draggable tag="ul" :list="metaFields.main.fieldList" item-key="key"
                  :group="{ name: 'dragGroup', pull: 'clone', put: false }" :move="checkFieldMove"
                  :clone="handleFieldWidgetClone" ghost-class="ghost" :sort="false">
                  <template #item="{ element: fld }">
                    <li class="field-widget-item" 
                        :title="fld.displayName" 
                        :class="{'virtual-field' : fld.virtualFlag}"
                        @dblclick="addFieldByDbClick(fld)">
                      <span><svg-icon :icon-class="fld.icon" class-name="color-svg-icon" />{{getMetaFieldLabel(fld)}}</span>
                    </li>
                  </template>
                </draggable>
              </el-collapse-item>
            </template>

            <template v-if="metaFields.detail && (metaFields.detail.length > 0)">
              <template v-for="(de, index) in metaFields.detail">
                <el-collapse-item :name="index + 2 + ''" :title="de.entityLabel">
                  <draggable tag="ul" :list="de.fieldList" item-key="key"
                    :group="{ name: 'dragGroup', pull: 'clone', put: false }" :move="checkFieldMove"
                    :clone="handleFieldWidgetClone" ghost-class="ghost" :sort="false">
                    <template #item="{ element: fld }">
                      <li class="field-widget-item" 
                          :title="fld.displayName"
                          :class="{'virtual-field' : fld.virtualFlag}"
                          @dblclick="addFieldByDbClick(fld)">
                        <span><svg-icon :icon-class="fld.icon" class-name="color-svg-icon" />{{ getMetaFieldLabel(fld)
                          }}</span>
                      </li>
                    </template>
                  </draggable>
                </el-collapse-item>
              </template>
            </template>
          </el-collapse>
        </el-tab-pane>

        <!-- 组件库 -->
        <el-tab-pane v-if="showComponentLib" name="componentLib">
          <template #label>
            <!-- <svg-icon icon-class="el-set-up" />  -->
            <span>{{ i18nt('designer.componentLib') }}</span>
          </template>

          <el-collapse v-model="activeNames" class="widget-collapse">
            <!-- 容器类 -->
            <el-collapse-item name="1" title="容器类">
              <draggable tag="ul" :list="containers" item-key="key"
                :group="{ name: 'dragGroup', pull: 'clone', put: false }" :clone="handleContainerWidgetClone"
                ghost-class="ghost" :sort="false" :move="checkContainerMove" @end="onContainerDragEnd">
                <template #item="{ element: ctn }">
                  <li class="container-widget-item" :title="ctn.displayName" @dblclick="addContainerByDbClick(ctn)">
                    <span><svg-icon :icon-class="ctn.icon" class-name="color-svg-icon" />{{ getWidgetLabel(ctn)
                      }}</span>
                  </li>
                </template>
              </draggable>
            </el-collapse-item>
            <!-- 基础类 -->
            <el-collapse-item name="2" title="基础类">
              <draggable tag="ul" :list="basicFields" item-key="key"
                :group="{ name: 'dragGroup', pull: 'clone', put: false }" :move="checkFieldMove"
                :clone="handleFieldWidgetClone" ghost-class="ghost" :sort="false">
                <template #item="{ element: fld }">
                  <li class="field-widget-item" :title="fld.displayName" @dblclick="addFieldByDbClick(fld)">
                    <span><svg-icon :icon-class="fld.icon" class-name="color-svg-icon" />{{ getWidgetLabel(fld)
                      }}</span>
                  </li>
                </template>
              </draggable>
            </el-collapse-item>
            <!-- 高级字段 -->
            <!-- <el-collapse-item name="3" :title="i18nt('designer.advancedFieldTitle')">
              <draggable tag="ul" :list="advancedFields" item-key="key" :group="{name: 'dragGroup', pull: 'clone', put: false}"
                        :move="checkFieldMove"
                        :clone="handleFieldWidgetClone" ghost-class="ghost" :sort="false">
                <template #item="{ element: fld }">
                  <li class="field-widget-item" :title="fld.displayName" @dblclick="addFieldByDbClick(fld)">
                    <span><svg-icon :icon-class="fld.icon" class-name="color-svg-icon" />{{getWidgetLabel(fld)}}</span>
                  </li>
                </template>
              </draggable>
            </el-collapse-item> -->
            <!-- 组织类 -->
            <el-collapse-item name="5" title="组织类">
              <draggable tag="ul" :list="organizeFileds" item-key="key"
                :group="{ name: 'dragGroup', pull: 'clone', put: false }" :move="checkFieldMove"
                :clone="handleFieldWidgetClone" ghost-class="ghost" :sort="false">
                <template #item="{ element: fld }">
                  <li class="field-widget-item" :title="fld.displayName" @dblclick="addFieldByDbClick(fld)">
                    <span><svg-icon :icon-class="fld.icon" class-name="color-svg-icon" />{{ getWidgetLabel(fld)
                      }}</span>
                  </li>
                </template>
              </draggable>
            </el-collapse-item>
            <!-- 业务类 -->
            <el-collapse-item name="6" title="业务类">
              <draggable tag="ul" :list="businessFields" item-key="key"
                :group="{ name: 'dragGroup', pull: 'clone', put: false }" :move="checkFieldMove"
                :clone="handleFieldWidgetClone" ghost-class="ghost" :sort="false">
                <template #item="{ element: fld }">
                  <li class="field-widget-item" :title="fld.displayName" @dblclick="addFieldByDbClick(fld)">
                    <span><svg-icon :icon-class="fld.icon" class-name="color-svg-icon" />{{ getWidgetLabel(fld)
                      }}</span>
                  </li>
                </template>
              </draggable>
            </el-collapse-item>
            <!-- 辅助类 -->
            <el-collapse-item name="7" title="辅助类">
              <draggable tag="ul" :list="auxiliaryFields" item-key="key"
                :group="{ name: 'dragGroup', pull: 'clone', put: false }" :move="checkFieldMove"
                :clone="handleFieldWidgetClone" ghost-class="ghost" :sort="false">
                <template #item="{ element: fld }">
                  <li class="field-widget-item" :title="fld.displayName" @dblclick="addFieldByDbClick(fld)">
                    <span><svg-icon :icon-class="fld.icon" class-name="color-svg-icon" />{{ getWidgetLabel(fld)
                      }}</span>
                  </li>
                </template>
              </draggable>
            </el-collapse-item>
            <!-- 自定义扩展字段 -->
            <el-collapse-item name="4" :title="i18nt('designer.customFieldTitle')">
              <draggable tag="ul" :list="customFields" item-key="key"
                :group="{ name: 'dragGroup', pull: 'clone', put: false }" :move="checkFieldMove"
                :clone="handleFieldWidgetClone" ghost-class="ghost" :sort="false">
                <template #item="{ element: fld }">
                  <li class="field-widget-item" :title="fld.displayName" @dblclick="addFieldByDbClick(fld)">
                    <span>
                      <svg-icon :icon-class="fld.icon" class-name="color-svg-icon" />{{ getWidgetLabel(fld) }}</span>
                  </li>
                </template>
              </draggable>
            </el-collapse-item>

          </el-collapse>

        </el-tab-pane>

        <!-- 表单模板 -->
        <el-tab-pane v-if="showFormTemplates" name="formLib" :key="ftcKey" style="padding: 8px">
          <template #label>
            <!-- <svg-icon icon-class="el-form-template" />  -->
            <span>{{ i18nt('designer.formLib') }}</span>
          </template>
          <template v-for="(ft, idx) in formTemplates">
            <el-card :bord-style="{ padding: '0' }" shadow="hover" class="ft-card">
              <el-popover placement="right" trigger="hover" popper-class="image-popover">
                <template #reference>
                  <img :src="ft.imgUrl" style="width: 200px; height: 200px">
                </template>
                <img :src="ft.imgUrl" style="height: 600px;width: 720px">
              </el-popover>
              <div class="bottom clear-fix">
                <span class="ft-title">#{{ idx + 1 }} {{ getFTTitle(ft) }}</span>
                <el-button link type="primary" class="right-button" @click="loadFormTemplate(ft.jsonUrl, ft.jsonStr)">
                  {{ i18nt('designer.hint.loadFormTemplate') }}</el-button>
              </div>
            </el-card>
          </template>
        </el-tab-pane>

        <!-- 数据域 -->
        <el-tab-pane v-if="showDataDomain" name="dataDomain" label="数据域" class="widget-collapse domainData-collapse">
          <el-tree :data="designer.formDomainData" :props="{
            'children': 'widgetList',
          }">
            <template #default="{ data }">
              <draggable v-if="data.type === 'sub-form' || data.type === 'grid-sub-form' || data.type === 'table-sub-form' || (data.formItemFlag && data.formItemFlag === true)" tag="div"
                :list="[data]" item-key="key" :group="{ name: 'dragGroup', pull: 'clone', put: false }"
                :move="dataDomainCheckFieldMove" :clone="handleDataDomainFieldWidgetClone" ghost-class="ghost"
                :sort="false" class="dataDomain-draggable">
                <template #item="{ element: data }">
                  <div class="field-widget-item flex align-items-center justify-content-start">
                    <div>
                      <svg-icon :icon-class="data.icon" class-name="color-svg-icon" />
                    </div>
                    <div class="pointer flex-1 flex">
                      <el-text :title="data.options.label" style="max-width: 140px; overflow: hidden;white-space: nowrap;text-overflow: ellipsis;">
                        {{ data.options.label }}
                      </el-text>

                      <span style="color: #a2a2a2;">
                        ({{ getWidgetLabel(data) }})
                      </span>

                      <div class="icon-del">
                        <el-popconfirm title="确定删除吗?" @confirm="handleDomainItemDel(data)">
                          <template #reference>
                            <el-icon class="field-widget-item-del">
                              <Delete />
                            </el-icon>
                          </template>
                        </el-popconfirm>
                      </div>
                    </div>
                  </div>
                </template>
              </draggable>
              <div v-else class="field-widget-item flex align-items-center justify-content-start">
                <div class="pointer flex-1 flex">
                  <el-text>
                    {{ data.options.label }}
                  </el-text>

                  <span style="color: #a2a2a2;">
                    ({{ getWidgetLabel(data) }})
                  </span>
                </div>
                <div>
                  <el-popconfirm title="确定删除吗?" @confirm="handleDomainItemDel(data)">
                    <template #reference>
                      <el-icon class="field-widget-item-del">
                        <Delete />
                      </el-icon>
                    </template>
                  </el-popconfirm>
                </div>
              </div>
            </template>
          </el-tree>
          <!-- <draggable tag="div" :list="designer.formDomainData" item-key="key" :group="{name: 'dragGroup', pull: 'clone', put: false}"
            :move="dataDomainCheckFieldMove"
            :clone="handleDataDomainFieldWidgetClone" ghost-class="ghost" :sort="false">
            <template #item="{ element: fld }">
              <div class="field-widget-item flex align-items-center justify-content-start">
                <div>
                  <svg-icon :icon-class="fld.icon" class-name="color-svg-icon" />
                </div>
                <div class="pointer flex-1 w-100px" :title="JSON.stringify(fld)">
                  <el-text>
                    {{ fld.options.label }}
                  </el-text>
                  
                  <span style="color: #a2a2a2;">
                    ({{ getWidgetLabel(fld) }})
                  </span>
                  <el-popconfirm title="确定删除吗?" @confirm="handleDomainItemDel(fld)">
                    <template #reference>
                      <el-icon class="field-widget-item-del">
                        <Delete />
                      </el-icon>
                    </template>
                  </el-popconfirm>
                </div>
              </div>
            </template>
          </draggable> -->
          <!-- 后期需确认如果不使用树形可以删掉  -->
          <!-- <el-tree
            :data="designer.formDomainData"
            :props="{
              'children': 'children',
            }"
          >
            <template #default="{ data }">
              <draggable v-if="data.formItemFlag && data.formItemFlag === true" tag="div" :list="[data]" item-key="key" :group="{name: 'dragGroup', pull: 'clone', put: false}"
                :move="dataDomainCheckFieldMove"
                :clone="handleDataDomainFieldWidgetClone" ghost-class="ghost" :sort="false">
                <template #item="{ element: fld }">
                  <div class="field-widget-item" :title="fld.displayName" @dblclick="addFieldByDbClick(fld)">
                    <span><svg-icon :icon-class="fld.icon" class-name="color-svg-icon" />{{ fld.options.label }} <span style="font-size: 10px;color: #050505">({{ getWidgetLabel(fld) }})</span></span>
                  </div>
                </template>
              </draggable>
              <div v-else>{{ getWidgetLabel(data) }}</div>
            </template>
          </el-tree> -->
        </el-tab-pane>
      </el-tabs>

    </div>
  </el-scrollbar>
</template>

<script>
import SvgIcon from '@/components/svg-icon/index.vue'
import {
  containers as CONS, basicFields as BFS, advancedFields as AFS, customFields as CFS, chartContainers as CHART_CONS,
  chartWidgets as CWS, organizeFileds as OFS, businessFields as BSFS, auxiliaryFields as AUFS
} from "./widgetsConfig"
import { setFormTemplate, formTemplates } from './templatesConfig'
import { addWindowResizeHandler, generateId } from "@/utils/util"
import i18n, { getLocale } from "@/utils/i18n"
import axios from 'axios'
import eventBus from "@/utils/event-bus"
import { getImg } from "@/api/upload/file"
import { debounce } from 'lodash'

// import ftImg1 from '@/assets/ft-images/t1.png'
// import ftImg2 from '@/assets/ft-images/t2.png'
// import ftImg3 from '@/assets/ft-images/t3.png'
// import ftImg4 from '@/assets/ft-images/t4.png'
// import ftImg5 from '@/assets/ft-images/t5.png'
// import ftImg6 from '@/assets/ft-images/t6.png'
// import ftImg7 from '@/assets/ft-images/t7.png'
// import ftImg8 from '@/assets/ft-images/t8.png'

export default {
  name: "FieldPanel",
  mixins: [i18n],
  components: {
    SvgIcon
  },
  props: {
    designer: Object,
  },
  inject: ['getBannedWidgets', 'getDesignerConfig'],
  data() {
    return {
      designerConfig: this.getDesignerConfig(),

      firstTab: 'componentLib',
      activeNames: ['1', '2', '3', '4', '5', '6', '7'],
      metadataActiveNames: ['0', '1', '2', '3', '4'],

      containers: [],
      commonContainers: [],
      basicFields: [],
      advancedFields: [],
      organizeFileds: [],
      businessFields: [],
      auxiliaryFields: [],
      customFields: [],
      chartContainers: [],
      chartWidgets: [],

      metaFields: {
        main: {
          entityName: '',
          entityLabel: '',
          fieldList: [
            {
              type: '',
              icon: '',
              displayName: '',
              options: {},
            }
          ]
        },
        detail: [
          {
            entityName: '',
            entityLabel: '',
            fieldList: [
              {
                type: '',
                icon: '',
                displayName: '',
                options: {},
              }
            ],

          }
        ]
      },

      formTemplates: [], // formTemplates
      ftcKey: 'ftc' + generateId(),
      // ftImages: [
      //   {imgUrl: ftImg1},
      //   {imgUrl: ftImg2},
      // ]
      // dataDomainData: JSON.parse(window.localStorage.getItem('widget__list__dataDomain')) || [],
      _thisViewWidget: [], // 缓存当前字段组件
      _thisCacheDomainWidght: [], // 缓存当前数据域组件（平铺）
    }
  },
  watch: {
    /**
     * 监听当前视图组件数据
     */
    'designer.widgetList': {
      handler(newVal) {
        // 添加防抖
        this.debouncedUpdate(newVal);
      },
      deep: true
    }
  },
  computed: {
    showComponentLib() {
      if (this.designerConfig['componentLib'] === undefined) {
        return true
      }

      return !!this.designerConfig['componentLib']
    },

    showFormTemplates() {
      if (this.designerConfig['formTemplates'] === undefined) {
        return true
      }

      return !!this.designerConfig['formTemplates']
    },

    showDataDomain() {
      if (this.designerConfig['dataDomain'] === undefined) {
        return true
      }

      return !!this.designerConfig['dataDomain']
    },

    showChartLib() {
      if (this.designerConfig['chartLib'] === undefined) {
        return false
      }

      return !!this.designerConfig['chartLib']
    },

    showMetadataLib() {
      if (this.designerConfig['metadataLib'] === undefined) {
        return false
      }

      return !!this.designerConfig['metadataLib']
    },

  },
  created() {
    // 数据域更新组件数据增加防抖
    this.debouncedUpdate = debounce((newVal) => {
      let newList = [];
      this.deepWidgetItemData([...newVal], this.designer.formDomainData, newList);
      this._thisViewWidget = newList;
      this.$nextTick(() => {
        window.localStorage.setItem('widget__list__dataDomain',
          JSON.stringify(this.designer.formDomainData)
        );
      });
    }, 200);

    if (!!this.designerConfig['chartLib']) {
      this.firstTab = 'chartLib'
    }

    if (!!this.designerConfig['metadataLib']) {
      this.firstTab = 'metadataLib'
    }

    this.loadWidgets();

    this.designer.handleEvent('refresh-form-templates', () => {
      this.ftcKey = 'ftc' + generateId()
    })

    this.getFormTemplatesData();

    // 监听数据域数据
    eventBus.$on('widget__list__dataDomain', (data) => {
      if (data) {
        const filterData = this.designer.formDomainData.find(item => item.key === data.key)
        // 扁平化根据存储的组件处理
        // const filterData = this._thisCacheDomainWidght.find(item => item.key === data.key)
        if (!filterData) {
          if (data.type === 'sub-form' || data.type === 'grid-sub-form' || daya.type === 'tab-sub-form') {
            this.designer.formDomainData.push({
              ...data,
              childFormItems: []
            })
          } else if (data.formItemFlag && data.formItemFlag === true) {
            this._thisCacheDomainWidght.push({
              ...data
            })
            this.designer.formDomainData.push({
              ...data
            })
          }
          window.localStorage.setItem('widget__list__dataDomain', JSON.stringify(this.designer.formDomainData))
        }
      }
    })
  },
  mounted() {
    //
  },
  methods: {
    /**
     * 获取表单模板数据
     */
    async getFormTemplatesData() {
      const list = await setFormTemplate();
      if (list.length > 0) {
        list.forEach(async (item) => {
          if (item.imgUrl) {
            const resImg = await getImg(item.imgUrl);
            item.imgUrl = window.URL.createObjectURL(resImg);
            item.jsonStr = JSON.stringify(item.jsonStr);
          }
        })
      }
      this.formTemplates = list;
    },

    /**
     * 提取字段组件，更新值
     * @param {Array} arr 新值
     * @param {Array} lists 旧值
     * @param {Array} newList 更新后的值
     */
    deepWidgetItemData(arr, lists, newList) {
      console.time('deepWidgetItemData');
      const startTime = performance.now();
      // 使用 Set 来优化查找性能
      const existingKeys = new Set(lists.map(item => item.key));
      const _thisCacheDomainWidght = this._thisCacheDomainWidght;
      // 添加计数器来跟踪处理的项目
      let processedItems = 0;
      let newItems = 0;
      let updatedItems = 0;

      // 递归处理函数
      const processItem = (item) => {
        processedItems++;
        if (item.type === 'sub-form') { // 后续开发时需确认这里是否需要判断增加等于 table-sub-form
          // 子表单处理
          if (!existingKeys.has(item.key)) {
            lists.push(item);
            existingKeys.add(item.key);
            newItems++;
          } else {
            const oldItem = lists.find(doItem => doItem.key === item.key);
            Object.assign(oldItem, item);
            this.findViewListUpdateKey(item.key, item);
            updatedItems++;
          }
          newList.push(item);
          return;
        }

        // 字段组件处理
        if (item.formItemFlag === true) {
          if (!existingKeys.has(item.key)) {
            _thisCacheDomainWidght.push(item);
            lists.push(item);
            existingKeys.add(item.key);
            newItems++;
          } else {
            const oldItem = lists.find(doItem => doItem.key === item.key);
            if (oldItem && JSON.stringify(oldItem.options) !== JSON.stringify(item.options)) {
              Object.assign(oldItem.options, item.options);
              this.findViewListUpdateKey(item.key, item.options);
              updatedItems++;
            }
          }
          newList.push(item);
        }

        // 处理子集
        const childList = item.cols || item.widgetList || item.rows;
        if (Array.isArray(childList) && childList.length > 0) {
          childList.forEach(processItem);
        }
      };

      // 处理数组
      arr.forEach(processItem);

      const endTime = performance.now();
      const duration = endTime - startTime;
      // 详细的性能日志
      console.group('deepWidgetItemData Performance');
      console.log(`总耗时: ${duration.toFixed(2)}ms`);
      console.log(`处理项目数: ${processedItems}`);
      console.log(`新增项目: ${newItems}`);
      console.log(`更新项目: ${updatedItems}`);
      console.log(`平均每项处理时间: ${(duration / processedItems).toFixed(2)}ms`);
      console.log(`最终列表大小: lists=${lists.length}, newList=${newList.length}`);
      console.groupEnd();
      console.timeEnd('deepWidgetItemData');

      // 如果处理时间超过某个阈值，可以输出警告
      if (duration > 100) { // 100ms作为示例阈值
        console.warn(`deepWidgetItemData 处理时间过长: ${duration.toFixed(2)}ms`);
      }
    },
    //更新所有视图数据
    async findViewListUpdateKey(key, options) {
      this.designer.widgetViewList.forEach(async item => {
        await deepFineKeyAndSetValue(item)
      })
      function deepFineKeyAndSetValue(doItem) {
        if (options.type === 'sub-form') { // 后续开发时需确认这里是否需要判断增加等于 table-sub-form
          let findIndex = options.widgetList.findIndex(subItem => subItem.key === doItem.key)
          if (findIndex !== -1) {
            Object.assign(doItem.options, options.widgetList[findIndex].options)
          }
        }
        if (doItem.key === key) {
          if (doItem.type === 'sub-form') { // 后续开发时需确认这里是否需要判断增加等于 table-sub-form
            Object.assign(doItem, options);
          } else {
            Object.assign(doItem.options, options);
          }
          return
        } else {
          for (let key of Object.keys(doItem)) {
            if (Array.isArray(doItem[key])) {
              doItem[key].forEach(item => {
                deepFineKeyAndSetValue(item)
              })
            }
          }
        }
      }

    },
    getMetaFieldLabel(widget) {
      const dName = widget.displayName
      return dName.substring(dName.indexOf('.') + 1, dName.length)
    },

    getWidgetLabel(widget) {
      if (!!widget.alias) {  //优先显示组件别名
        return this.i18n2t(`designer.widgetLabel.${widget.alias}`, `extension.widgetLabel.${widget.alias}`)
      }

      return this.i18n2t(`designer.widgetLabel.${widget.type}`, `extension.widgetLabel.${widget.type}`)
    },

    isBanned(wName) {
      return this.getBannedWidgets().indexOf(wName) > -1
    },

    getFTTitle(ft) {
      const langName = getLocale()
      if (!!ft.i18n && !!ft.i18n[langName]) {
        return ft.i18n[langName].title || ft.title
      } else {
        return ft.title
      }
    },

    loadWidgets() {
      console.time('loadWidgets');
      const startTime = performance.now();

      // 创建一个通用的映射函数来减少代码重复
      const mapWidgets = (items, options = {}) => {
        const { internal = false } = options;
        // 预先计算banned类型集合,使用Set提升查找性能
        const bannedTypes = new Set(this.getBannedWidgets());
        // 批量创建keys以减少generateId()调用次数
        const keys = Array(items.length).fill(null).map(() => generateId());

        return items.map((item, index) => {
          // 提前检查过滤条件,避免创建不必要的对象
          if ((internal && item.internal) || bannedTypes.has(item.type)) {
            return null;
          }

          return {
            key: keys[index],
            ...item,
            displayName: this.i18n2t(
              `designer.widgetLabel.${item.type}`, 
              `extension.widgetLabel.${item.type}`
            )
          };
        }).filter(Boolean); // 过滤掉null值
      };

      // 批量处理所有widget类型
      const mappedData = {
        containers: mapWidgets(CONS, { internal: true }),
        basicFields: mapWidgets(BFS),
        advancedFields: mapWidgets(AFS),
        organizeFileds: mapWidgets(OFS),
        businessFields: mapWidgets(BSFS),
        auxiliaryFields: mapWidgets(AUFS),
        customFields: mapWidgets(CFS),
        chartContainers: mapWidgets(CHART_CONS, { internal: true }),
        chartWidgets: mapWidgets(CWS)
      };

      // 一次性赋值以减少响应式更新次数
      Object.assign(this, mappedData);
      // 单独处理commonContainers因为它依赖containers
      this.commonContainers = this.containers.filter(con => !!con.commonFlag);

      const endTime = performance.now();
      console.timeEnd('loadWidgets');
      console.log(`loadWidgets execution time: ${endTime - startTime}ms`);
    },

    handleContainerWidgetClone(origin) {
      return this.designer.copyNewContainerWidget(origin)
    },

    handleFieldWidgetClone(origin) {
      return this.designer.copyNewFieldWidget(origin)
    },

    /**
     * 数据域clone组件方法 处理数据域拖动后判断不重复才可赋值组件
     * @param {*} origin
     */
    handleDataDomainFieldWidgetClone(origin) {
      // 使用 Set 提升查找性能
      const existingKeys = new Set(this._thisViewWidget.map(item => item.key));
      
      if (origin.type === 'sub-form') { // 后续开发时需确认这里是否需要判断增加等于 table-sub-form
        // 使用 some 替代 forEach + flag
        const hasExistingItem = origin.widgetList.some(subItem => 
          existingKeys.has(subItem.key)
        );
        
        if (hasExistingItem) {
          this.$message.warning('当前子表单中的字段组件已在当前视图存在，请勿重复添加');
          return undefined;
        }
      }
      
      // 使用 Set 来优化查找
      const isExisting = this._thisViewWidget.some(item => {
        if (item.type === 'sub-form') { // 后续开发时需确认这里是否需要判断增加等于 table-sub-form
          return item.key === origin.key || 
                 item.widgetList.some(subItem => subItem.key === origin.key);
        }
        return item.key === origin.key;
      });
      
      return !isExisting ? this.designer.copyNewFieldWidget(origin, false) : undefined;
    },

    /**
     * 数据域删除方法
     * @param {*} origin 
     */
    handleDomainItemDel(origin) {
      console.log('origin', origin)
      this.designer.formDomainData = this.designer.formDomainData.filter(item => item.key !== origin.key)
      window.localStorage.setItem('widget__list__dataDomain', JSON.stringify([...this.designer.formDomainData]))

      this.handleCommonDeepData(this.designer.widgetViewList, origin.key, (arr, item, i, key) => {
        arr.splice(i, 1);
      })
      this.handleCommonDeepData(this.designer.widgetList, origin.key, (arr, item, i, key) => {
        arr.splice(i, 1);
      })
      this.designer.saveFormContentToStorage()
    },

    /**
     * 递归删除数据
     */
    handleCommonDeepData(arr, key, callback) {
      for (let i = 0; i < arr.length; i++) {
        const item = arr[i];
        if (item.key !== undefined && item.key === key) {
          callback && callback(arr, item, i, key);
          return
        } else {
          if ((item.cols && item.cols.length > 0) || (item.widgetList && item.widgetList.length > 0) || (item.rows && item.rows.length > 0)) {
            const list = item.cols || item.widgetList || item.rows
            this.handleCommonDeepData(list, key, callback)
          }
        }
      }
    },

    /* draggable组件的move钩子是在内部子组件被拖放到其他draggable组件时触发！！ */
    checkContainerMove(evt) {
      return this.designer.checkWidgetMove(evt)
    },

    /* draggable组件的move钩子是在内部子组件拖放到其他draggable组件时触发！！ */
    checkFieldMove(evt) {
      return this.designer.checkFieldMove(evt)
    },
    dataDomainCheckFieldMove(evt) {
      console.log('******************evt******************', evt)
      console.log('***this._thisViewWidget***', this._thisViewWidget)
      const origin = evt.draggedContext.element
      const _thisViewObj = this._thisViewWidget.find(item => item.key === origin.key)
      // if (this._thisViewWidget.length === 0 || !_thisViewObj) {
      return this.designer.checkFieldMove(evt)
      // } else {
      //   return false;
      // }
    },

    onContainerDragEnd(evt) {
      //console.log('Drag end of container: ')
      //console.log(evt)
    },

    addContainerByDbClick(container) {
      this.designer.addContainerByDbClick(container)
    },

    addFieldByDbClick(widget) {
      this.designer.addFieldByDbClick(widget)
    },

    addChartContainerByDbClick(container) {
      this.designer.addChartContainerByDbClick(container)
    },

    addChartByDbClick(chart) {
      this.designer.addChartByDbClick(chart)
    },
    // 加载表单模板
    loadFormTemplate(jsonUrl, jsonStr) {
      this.$confirm(this.i18nt('designer.hint.loadFormTemplateHint'), this.i18nt('render.hint.prompt'), {
        confirmButtonText: this.i18nt('render.hint.confirm'),
        cancelButtonText: this.i18nt('render.hint.cancel')
      }).then(() => {
        if (!!jsonStr) {
          if (typeof jsonStr === 'string') {
            this.designer.loadFormJson(JSON.parse(jsonStr))
          } else {
            this.designer.loadFormJson(jsonStr)
          }
          this.$message.success(this.i18nt('designer.hint.loadFormTemplateSuccess'))
          return
        }

        axios.get(jsonUrl).then(res => {
          let modifiedFlag = false
          if (typeof res.data === 'string') {
            modifiedFlag = this.designer.loadFormJson(JSON.parse(res.data))
          } else if (res.data.constructor === Object) {
            modifiedFlag = this.designer.loadFormJson(res.data)
          }
          if (modifiedFlag) {
            this.designer.emitHistoryChange()
          }

          this.$message.success(this.i18nt('designer.hint.loadFormTemplateSuccess'))
        }).catch(error => {
          this.$message.error(this.i18nt('designer.hint.loadFormTemplateFailed') + ':' + error)
        })
      }).catch(error => {
        console.error(error)
      })
    },

    setMetaFields(metaFields) {
      this.metaFields = metaFields
    }

  }

}
</script>

<style lang="scss" scoped>
:deep(.el-tabs__item) {
  padding: 0 10px !important;
}

.color-svg-icon {
  -webkit-font-smoothing: antialiased;
  color: #7c7d82;
}

.side-scroll-bar {
  :deep(.el-scrollbar__wrap) {
    overflow-x: hidden;
  }
}

div.panel-container {
  padding-bottom: 10px;
}

.no-bottom-margin :deep(.el-tabs__header) {
  margin-bottom: 0;
}

.indent-left-margin {
  :deep(.el-tabs__nav) {
    margin-left: 20px;
  }
}

.el-collapse-item :deep(ul)>li {
  list-style: none;
}

.widget-collapse {
  border-top-width: 0;

  :deep(.el-collapse-item__header) {
    margin-left: 8px;
    font-style: italic;
    font-weight: bold;
  }

  :deep(.el-collapse-item__content) {
    padding-bottom: 6px;

    ul {
      padding-left: 10px;
      /* 重置IE11默认样式 */
      margin: 0;
      /* 重置IE11默认样式 */
      margin-block-start: 0;
      margin-block-end: 0.25em;
      padding-inline-start: 10px;

      &:after {
        content: "";
        display: block;
        clear: both;
      }

      .container-widget-item,
      .field-widget-item,
      .chart-container-widget-item,
      .chart-widget-item {
        //text-align: center; // 居中显示不太美观
        display: inline-block;
        height: 32px;
        line-height: 32px;
        width: 98px;
        float: left;
        margin: 2px 6px 6px 0;
        cursor: move;
        white-space: nowrap;
        text-overflow: ellipsis;
        overflow: hidden;
        background: #fff;
        border: 1px solid #DCDFE6;
        border-radius: 4px;
        padding: 0 8px;
      }

      .container-widget-item:hover, .field-widget-item:hover, .chart-container-widget-item:hover, .chart-widget-item:hover {
        background: #F1F2F3;
        border-color: $--color-primary;

        .color-svg-icon {
          color: $--color-primary;
        }
      }

      .field-widget-item.virtual-field {
        background: #F1F1F1;
        border: 1px dashed #DCDFE6;
      }

      .field-widget-item.virtual-field:hover {
        background: #F1F1F1;
        border: 1px dashed $--color-primary;

        .color-svg-icon {
          color: $--color-primary;
        }
      }

      .chart-container-widget-item, .chart-widget-item {
        cursor: default !important;
      }

      .drag-handler {
        position: absolute;
        top: 0;
        left: 160px;
        background-color: #dddddd;
        border-radius: 5px;
        padding-right: 5px;
        font-size: 11px;
        color: #666666;
      }
    }
  }
  
  .dataDomain-draggable {
    flex: 1;
    .pointer {
      width: 0;
      .icon-del {
        display: flex;
        align-items: center;
        justify-content: center;
        margin-right: 4px;
      }
    }
  }
}

.domainData-collapse {
  .field-widget-item {
    margin-top: 8px;
  }

  .field-widget-item:last-child {
    margin-top: 0px;
  }

  .field-widget-item-del {
    display: none;
    margin-left: 10px;
  }

  .field-widget-item:hover {
    .field-widget-item-del {
      display: inline-block;
    }
  }
}

.el-card.ft-card {
  border: 1px solid #8896B3;
}

.ft-card {
  margin-bottom: 10px;

  .bottom {
    margin-top: 10px;
    line-height: 12px;
  }

  /*
    .image-zoom {
      height: 500px;
      width: 620px
    }
    */

  .ft-title {
    font-size: 13px;
    font-weight: bold;
  }

  .right-button {
    padding: 0;
    float: right;
  }

  .clear-fix:before,
  .clear-fix:after {
    display: table;
    content: "";
  }

  .clear-fix:after {
    clear: both;
  }
}

.w-100px {
  width: 100px;
  white-space: sp;
}
</style>
<style lang="scss">
.image-popover {
  width: 750px !important;
}
</style>
